using AnimCollections;
using Unity.Collections;

namespace DA.AnimGraph {
    public unsafe struct PostScopeContext {
        float localWeight;

        CurveBuffer<CurveSample>* curveBuffer;
        CurveBuffer<CurveSample>.Writer<CurveSample> curveBufferWriter;

        public PostScopeContext(CurveBuffer<CurveSample>* curveBuffer) {
            localWeight = 1;
            this.curveBuffer = curveBuffer;
            curveBufferWriter = curveBuffer->GetWriter();
        }
        public PostScopeContext(ref PostScopeContext parent, float weight) {
            localWeight = weight;
            curveBuffer = parent.curveBuffer;
            curveBufferWriter = curveBuffer->GetWriter();
        }

        public void AddCurve(CurveSample sample) {
            curveBufferWriter.Add(sample);
        }
        public UnsafeArrayReader<CurveSample> GetCurveSamples() {
            return curveBuffer->DumpAllData();
        }

        public void Fusion(ref PostScopeContext other) {
            //curveBuffer->CheckVersion(curveBufferWriter, other.curveBufferWriter);
            curveBufferWriter.Fix();
            other.curveBufferWriter.Fix();

            if (other.curveBufferWriter.count == 0) return;
            else if (curveBufferWriter.count == 0) {
                curveBufferWriter.OverrideFusion(ref other.curveBufferWriter);

                var ptr = curveBufferWriter.GetArrayPtr();
                var count = curveBufferWriter.count;
                var weight = other.localWeight;
                for (int i = 0; i < count; i++) {
                    var temp = ptr + i;
                    temp->value *= weight;
                }
            } else {
                // 双方皆不为空
                // 双线合并
                float weightB = other.localWeight;
                int countA = curveBufferWriter.count;
                int countB = other.curveBufferWriter.count;
                int iterA = 0, iterB = 0, iterR = 0;
                CurveSample* arrayA = curveBufferWriter.GetArrayPtr();
                CurveSample* arrayB = other.curveBufferWriter.GetArrayPtr();
                int capacity = countA + countB;
                var resultArray = stackalloc CurveSample[capacity];
                //Span<CurveSample> resultArray = new(resultPtr, capacity);
                while (true) {
                    if (iterA == countA && iterB < countB) {
                        for (; iterB < countB; ++iterB, ++iterR) {
                            var itemB = arrayB + iterB;
                            resultArray[iterR] = new CurveSample(itemB->name, itemB->value * weightB);
                        }
                        break;
                    }
                    if (iterB == countB && iterA < countA) {
                        for (; iterA < countA; ++iterA, ++iterR) {
                            var itemA = arrayA + iterA;
                            resultArray[iterR] = new CurveSample(itemA->name, itemA->value);
                        }
                        break;
                    }
                    if (iterB == countB && iterA == countA) {
                        break;
                    }

                    var elementA = arrayA + iterA;
                    var elementB = arrayB + iterB;

                    if (elementA->name == elementB->name) {
                        resultArray[iterR] = new CurveSample(elementA->name, elementA->value + elementB->value * weightB);
                        ++iterA;
                        ++iterB;
                        ++iterR;
                    } else if (elementA->name < elementB->name) {
                        resultArray[iterR] = new CurveSample(elementA->name, elementA->value);
                        ++iterA;
                        ++iterR;
                    } else {
                        resultArray[iterR] = new CurveSample(elementA->name, elementB->value * weightB);
                        ++iterB;
                        ++iterR;
                    }
                }
                // 写入buffer
                curveBuffer->CheckSpace(ref curveBufferWriter, other.curveBufferWriter, iterR, resultArray);
            }

        }


    }
}
